1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.collect;
18
19 import static com.google.common.base.Preconditions.checkNotNull;
20
21 import java.util.Iterator;
22 import java.util.LinkedList;
23 import java.util.Queue;
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 public abstract class TreeTraverser<T> {
48
49
50
51
52 public abstract Iterable<T> children(T root);
53
54
55
56
57
58
59
60
61 public final FluentIterable<T> preOrderTraversal(final T root) {
62 checkNotNull(root);
63 return new FluentIterable<T>() {
64 @Override
65 public UnmodifiableIterator<T> iterator() {
66 return preOrderIterator(root);
67 }
68 };
69 }
70
71
72 UnmodifiableIterator<T> preOrderIterator(T root) {
73 return new PreOrderIterator(root);
74 }
75
76 private final class PreOrderIterator extends UnmodifiableIterator<T> {
77 private final LinkedList<Iterator<T>> stack;
78
79 PreOrderIterator(T root) {
80 this.stack = Lists.newLinkedList();
81 stack.addLast(Iterators.singletonIterator(checkNotNull(root)));
82 }
83
84 @Override
85 public boolean hasNext() {
86 return !stack.isEmpty();
87 }
88
89 @Override
90 public T next() {
91 Iterator<T> itr = stack.getLast();
92 T result = checkNotNull(itr.next());
93 if (!itr.hasNext()) {
94 stack.removeLast();
95 }
96 Iterator<T> childItr = children(result).iterator();
97 if (childItr.hasNext()) {
98 stack.addLast(childItr);
99 }
100 return result;
101 }
102 }
103
104
105
106
107
108
109
110
111 public final FluentIterable<T> postOrderTraversal(final T root) {
112 checkNotNull(root);
113 return new FluentIterable<T>() {
114 @Override
115 public UnmodifiableIterator<T> iterator() {
116 return postOrderIterator(root);
117 }
118 };
119 }
120
121
122 UnmodifiableIterator<T> postOrderIterator(T root) {
123 return new PostOrderIterator(root);
124 }
125
126 private static final class PostOrderNode<T> {
127 final T root;
128 final Iterator<T> childIterator;
129
130 PostOrderNode(T root, Iterator<T> childIterator) {
131 this.root = checkNotNull(root);
132 this.childIterator = checkNotNull(childIterator);
133 }
134 }
135
136 private final class PostOrderIterator extends AbstractIterator<T> {
137 private final LinkedList<PostOrderNode<T>> stack;
138
139 PostOrderIterator(T root) {
140 this.stack = Lists.newLinkedList();
141 stack.addLast(expand(root));
142 }
143
144 @Override
145 protected T computeNext() {
146 while (!stack.isEmpty()) {
147 PostOrderNode<T> top = stack.getLast();
148 if (top.childIterator.hasNext()) {
149 T child = top.childIterator.next();
150 stack.addLast(expand(child));
151 } else {
152 stack.removeLast();
153 return top.root;
154 }
155 }
156 return endOfData();
157 }
158
159 private PostOrderNode<T> expand(T t) {
160 return new PostOrderNode<T>(t, children(t).iterator());
161 }
162 }
163
164
165
166
167
168
169
170
171 public final FluentIterable<T> breadthFirstTraversal(final T root) {
172 checkNotNull(root);
173 return new FluentIterable<T>() {
174 @Override
175 public UnmodifiableIterator<T> iterator() {
176 return new BreadthFirstIterator(root);
177 }
178 };
179 }
180
181 private final class BreadthFirstIterator extends UnmodifiableIterator<T>
182 implements PeekingIterator<T> {
183 private final Queue<T> queue;
184
185 BreadthFirstIterator(T root) {
186 this.queue = Lists.newLinkedList();
187 queue.add(checkNotNull(root));
188 }
189
190 @Override
191 public boolean hasNext() {
192 return !queue.isEmpty();
193 }
194
195 @Override
196 public T peek() {
197 return queue.element();
198 }
199
200 @Override
201 public T next() {
202 T result = queue.remove();
203 for (T child : children(result)) {
204 queue.add(checkNotNull(child));
205 }
206 return result;
207 }
208 }
209 }